package com.rocsea.robot.service;

import com.rocsea.robot.config.build.KettleBuildConfig;
import com.rocsea.robot.config.jdbc.common.JdbcConfig;
import com.rocsea.robot.config.kettlepack.KettlePackConfig;
import com.rocsea.robot.factory.KettleBuildDatabaseFactory;
import com.rocsea.robot.model.bo.KettlePack;
import com.rocsea.robot.model.enums.KettleBuildModuleEnum;
import com.rocsea.robot.model.bo.KpBuildInfo;
import com.rocsea.robot.utils.DatabaseUtils;
import com.rocsea.robot.utils.KettleBuildUtils;
import com.rocsea.robot.utils.MysqlBuilderUtils;
import com.rocsea.robot.utils.UidUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;

import static com.rocsea.robot.constant.KettleBuildConstant.getCategoryId;

import static com.rocsea.robot.constant.KettlePackBuildConstant.*;
import static com.rocsea.robot.constant.KettlePackBuildConstant.KETTLE_PACK_TABLE_NAME;

/**
 * @Author RocSea
 * @Date 2023/1/31
 */
@Component
public class KettlePackService {
    @Resource
    private KettlePackConfig kettlePackConfig;

    @Resource
    private KettleBuildConfig buildConfig;

    public String buildKettlePack(KpBuildInfo kpBuildInfo) {
        String taskName = kpBuildInfo.getTaskName();
        String tableName = kpBuildInfo.getTableName();
        String jobName = kpBuildInfo.getJobName();
        Boolean r = ifBuildKettlePack(taskName);
        StringBuilder sql = new StringBuilder();
        if (r) {
            // build kettle-pack normal task
            KettlePack normal = buildKettlePackBo();
            normal.setJobName(jobName);
            normal.setJobPath(getJobPathPrefix() + "/start_job_sync_" + tableName);
            normal.setJobParams(kpBuildInfo.getJobParam());
            normal.setJobQuartz(getRandomTime(CRON_MINUTE_LEVEL, 20));
            sql.append(MysqlBuilderUtils.buildKettlePack(normal));

            // build kettle-pack compensation task
            if(Objects.nonNull(kpBuildInfo.getJobCompensationParam())){
                KettlePack compensation = buildKettlePackBo();
                compensation.setJobName(jobName + "(补偿)");
                compensation.setJobPath(getJobPathPrefix() + "/start_job_sync_" + tableName);
                compensation.setJobParams(kpBuildInfo.getJobCompensationParam());
                compensation.setJobQuartz(getRandomTime(CRON_ONE_HOUR_LEVEL, 30));
                sql.append(MysqlBuilderUtils.buildKettlePack(compensation));
            }
        }
        return sql.toString();
    }

    private Boolean ifBuildKettlePack(String jobName) {
        if (Boolean.FALSE == buildConfig.getKettleBuildEnable().getKettlePack()) {
            return false;
        }
        JdbcConfig jdbcConfig = KettleBuildDatabaseFactory.getDatabase(KettleBuildModuleEnum.ONSHORE.getText());
        Map<String, Object> params = new HashMap<>(2);
        params.put(KP_JOB_COLUMN_JOB_NAME, jobName);
        Optional<Long> tableCount = DatabaseUtils.getTableCount(jdbcConfig.getUrl(), jdbcConfig.getUsername(),
                jdbcConfig.getPassword(), KETTLE_PACK_SCHEMA_NAME, KETTLE_PACK_TABLE_NAME, params);
        return tableCount.orElse(0L) < 1;
    }

    private KettlePack buildKettlePackBo() {
        int moduleType = KettleBuildUtils.getModuleType();
        KettlePack kettlePackBo = new KettlePack();
        String categoryId = getCategoryId(moduleType);
        String carteId = getCarteId();
        kettlePackBo.setId(UidUtils.getUuid());
        kettlePackBo.setCategoryId(categoryId);
        kettlePackBo.setRemoteServer(carteId);
        kettlePackBo.setCreateTime(new Date());
        kettlePackBo.setCreateBy("admin");
        kettlePackBo.setJobType("rep");
        kettlePackBo.setJobLogLevel("Basic");
        kettlePackBo.setJobStatus(2);
        kettlePackBo.setErrorAlarmFlag(1);
        kettlePackBo.setDelFlag(0);
        kettlePackBo.setRunConfig("remote");
        kettlePackBo.setJobRepositoryId(KP_JOB_REPOSITORY_ID);
        return kettlePackBo;
    }

    private String getCarteId() {
        Random r = new Random();
        int n = r.nextInt(10) + 1;
        String[] arr = kettlePackConfig.getCarteIds();
        return arr[n % 5];
    }

    private String getJobPathPrefix() {
        int moduleType = KettleBuildUtils.getModuleType();
        String sourceSchemaName = KettleBuildUtils.getSourceSchemaName();
        String sourceTableName = KettleBuildUtils.getSourceTableName();
        return getDirPath(moduleType, sourceSchemaName, sourceTableName);
    }

    private String getDirPath(int type, String schemaName, String tableName) {
        String path = "";
        switch (type) {
            case 1:
                path = "/international";
                break;
            case 2:
                path = "/dm";
                break;
            case 6:
                path = "/onshore";
                break;
            case 41:
                path = "/third_part";
                break;
        }
        return path + "/" + schemaName + "/" + tableName;
    }

    private String getRandomTime(String cron, int minuteMax) {
        Random r = new Random();
        int minute = r.nextInt(minuteMax);
        int second = r.nextInt(60);
        String minuteString = String.valueOf(minute);
        String secondString = String.valueOf(second);
        if (minute < 10) {
            minuteString = 0 + minuteString;
        }
        if (second < 10) {
            secondString = 0 + secondString;
        }

        return cron.replace("mm", minuteString).replace("ss", secondString);
    }


    public String buildKettlePackWithSharding() {
        StringBuilder sql = new StringBuilder();
        String tableName = KettleBuildUtils.getSourceTableName();
        String jobName = getJobName();
        String outTableName = KettleBuildUtils.getTargetTableName();
        Boolean r = ifBuildKettlePack(jobName);
        if (r) {
            String[] region = buildConfig.getKettleBuildSharding().getRegion().split("-");
            for (int year = Integer.parseInt(region[0]); year <= Integer.parseInt(region[1]); year++) {
                String realOutTableName = outTableName;
                if (outTableName.endsWith("_")) {
                    realOutTableName = outTableName + year;
                }
                KettlePack normal = buildKettlePackBo();
                // 构建kettle-pack 正常任务
                String jobParams = String.format("{\"tableName\":\"%s\",\"compensation_type\":\"2\"" +
                                ",\"page_size\":\"5000\",\"commit_size\":\"1000\",\"outTableName\":\"%s\",\"year\":\"%s\"}"
                        , tableName, realOutTableName, year);
                normal.setJobName(jobName + "_" + year + "(sharding)");
                normal.setJobPath(getJobPathPrefix() + "/start_" + tableName + "(sharding)");
                normal.setJobParams(jobParams);
                normal.setJobQuartz(getRandomTime(CRON_MINUTE_LEVEL, 20));
                sql.append(MysqlBuilderUtils.buildKettlePack(normal));

                KettlePack compensation = buildKettlePackBo();
                // 构建kettle-pack 补偿任务
                String compensationJobParam = String.format("{\"tableName\":\"%s\",\"compensation_type\":\"1\"" +
                                ",\"page_size\":\"5000\",\"commit_size\":\"1000\",\"outTableName\":\"%s\",\"year\":\"%s\"}"
                        , tableName, realOutTableName, year);
                compensation.setJobName(jobName + "_" + year + "(sharding_补偿)");
                compensation.setJobPath(getJobPathPrefix() + "/start_" + tableName + "(sharding)");
                compensation.setJobParams(compensationJobParam);
                compensation.setJobQuartz(getRandomTime(CRON_ONE_HOUR_LEVEL, 30));
                sql.append(MysqlBuilderUtils.buildKettlePack(compensation));

                // 构建 kettle-pack sharding配置任务
                if (year == Integer.parseInt(region[1])) {
                    KettlePack config = buildKettlePackBo();
                    String sourceSchemaName = KettleBuildUtils.getSourceSchemaName();
                    String jobParam = String.format("{\"tableName\":\"%s\",\"tableSchema\":\"%s\"}", tableName, sourceSchemaName);
                    config.setJobQuartz(buildConfig.getKettleBuildSharding().getConfigCron());
                    config.setJobName(jobName + "(sharding_config)");
                    config.setJobParams(jobParam);
                    config.setJobPath(SHARDING_CONFIG_PATH);
                    sql.append(MysqlBuilderUtils.buildKettlePack(config));
                }
            }
        }
        return sql.toString();
    }

    private String getJobName() {
        String jobName = KettleBuildUtils.getSourceTableName();
        String sourceSchemaName = KettleBuildUtils.getSourceSchemaName();
        if (StringUtils.isNotEmpty(buildConfig.getOutDatabase())) {
            jobName = sourceSchemaName + "-" + jobName;
        }
        return jobName;
    }
}
